#include "herm/base/container/buffer.h"
#include "herm/base/utils/misc.h"     // ST_SUCCESS
#include "herm/base/socket/stream.h"
#include "herm/base/socket/multiplexor.h"
#include "accept_handler.h"

AcceptHandler::AcceptHandler()
{
	m_acceptor = nullptr;
	m_acceptSocks = nullptr;
}

AcceptHandler::~AcceptHandler()
{
	Close();

	HERM_DELETE(m_acceptor);
	HERM_DELETE(m_acceptSocks);
}

void AcceptHandler::Reset(const herm::Address& addr, herm::Multiplexor* multiplexor, int acceptQueueSize)
{
	m_state = herm::SetState(herm::ST_SUCCESS, 0);
	m_multiplexor = multiplexor;
	delete m_acceptor;
	m_acceptor = new herm::Acceptor(addr, true);
#ifdef ENABLE_EDGE_TRIGGER
	m_acceptor->SetNonblock();
#endif
	m_multiplexor->Register(this, herm::READ_MASK);
	delete m_acceptSocks;
	m_acceptSocks = new herm::Buffer(acceptQueueSize * sizeof(herm::Handle));
}

void AcceptHandler::Close()
{
    if (m_acceptor)
	    m_acceptor->Close();
}

herm::Handle AcceptHandler::OnGetHandle() const
{
	return m_acceptor->GetHandle();
}

int AcceptHandler::OnReceive(int)
{
	try
	{
#ifdef ENABLE_EDGE_TRIGGER
		while (true)
		{
			if (m_acceptSocks->Full())
				return herm::ST_SUCCESS;

			herm::Stream s;
			int ret = m_acceptor->AcceptNB(s);
			if (ret == herm::COMPLETION)
				break;

			herm::Handle sock = s.Detach();
			m_acceptSocks->Push(reinterpret_cast<const char*>(&sock), sizeof(sock));
		}
#else
		if (m_acceptSocks->Full())
			return herm::ST_SUCCESS;

		herm::Stream s;
		m_acceptor->Accept(s);

		herm::Handle sock = s.Detach();
		m_acceptSocks->Push(reinterpret_cast<const char*>(&sock), sizeof(sock));
#endif
	}
	catch (const herm::SocketException& e)
	{
		std::string msg = e.Desc();
		return herm::ST_ACCEPT_FAILED;
	}

	return herm::ST_SUCCESS;
}

int AcceptHandler::OnSend(int)
{
	return herm::ST_SUCCESS;
}

void AcceptHandler::OnError(int stateType, int stateCode)
{
	if (herm::IsValidState(m_state))
		m_state = herm::SetState(stateType, stateCode);
}

